package btree;

import java.util.ArrayList;

import settings.Global;

import data.DiskPage;

public class BTree {
	ArrayList<DiskPage> al_diskpages = new ArrayList<DiskPage>();
	private BNode root;
	private BNode rightMostNode;
	
	//constructor - since I am only dealing with bulk loading, just accept the diskpages right away
	public BTree(ArrayList<DiskPage> aldp){
		al_diskpages=aldp;
		root=new BNode(); //points to data
		rightMostNode=root; //is the root
		
		//add data
		root.addDiskPage(al_diskpages.get(0));
		al_diskpages.remove(0); //delete
		
		//now bulk load the tree
		bulkLoadBPlusTree();
	}

	//getter
	public BNode getRoot(){
		return root;
	}
	
	
	//for bulk loading
	protected void bulkLoadBPlusTree(){
		//iterate over the al_diskpage
		while(al_diskpages.size()>0){
			insertBulk(rightMostNode, al_diskpages.get(0));
			al_diskpages.remove(0);
		}		
	}
	
	//takes the rightmost node to insert a diskpage into
	//
	protected void insertBulk(BNode node, DiskPage dp){
		//try adding
		if(node.addDiskPage(dp)){
			//success
		}
		else{//full - split
			split(node,dp);
		}
	}
	
	protected void split(BNode node, DiskPage dp){
		//make another node to hold information
		BNode bpn = new BNode();//points to data 
		
		//move half data
		bpn.addDiskPage(dp);
		//remove this value from the pointer
		DiskPage temp = node.remove();
		
		//update pointers
		bpn.parent=rightMostNode.parent;
		
		//insert data into parent
		//root
		if(node.parent==null){
			BNode newRoot = new BNode(); //create it
			root = newRoot; //update BTree root
			newRoot.addDiskPage(temp); //add diskpage
			//update pointers
			newRoot.child1=node;
			newRoot.child2=bpn;			
		}
		else{//dealing with another node that is already there
			BNode parent = node.parent;
			
			//can add the new one
			if(parent.numPages==1){
				parent.addDiskPage(temp);
				parent.child3=bpn;//update pointer
			}
			else{//need to split the parent
				splitParent(parent,bpn,temp);
			}
		}
	}
	
	//split a parent node that has pointers
	protected void splitParent(BNode parent, BNode right, DiskPage dp){
		BNode parent2 = new BNode();
		//move half data
		parent2.addDiskPage(dp);
		DiskPage temp = parent.remove();
		
		//update pointers
		parent2.parent=parent.parent;
		parent2.child1=parent.child3;
		parent2.child2=right;
		
		//insert into parent.parent
		if(parent.parent==null){
			BNode newRoot = new BNode(); //create it
			root = newRoot; //update BTree root
			newRoot.addDiskPage(temp); //add diskpage
			//update pointers
			newRoot.child1=parent;
			newRoot.child2=parent2;			
		}
		else{//dealing with another node that is already there
			BNode parentMega = parent.parent;
			
			//can add the new one
			if(parentMega.numPages==1){
				parentMega.addDiskPage(temp);
				parentMega.child3=parent2;//update pointer
			}
			else{//need to split the parent
				splitParent(parentMega,parent2,temp);
			}
		}
	}
}
